#include "ScoreModel.h"
#include "UpdateScoreNetworkEvent.h"
#include "AddScorePlayerNetworkEvent.h"
#include "GameOverNetworkEvent.h"
#include <cmath>
#include <climits>

ScoreModel::ScoreModel(PlayersPtr players)
    : players(players)
{
}

ScoreModel::~ScoreModel()
{
}

void ScoreModel::init()
{
    PlayerIds ids = players->getPlayerIds();
    for (PlayerIds::iterator it = ids.begin(); it != ids.end(); ++it)
    {
        Model* model = new Model();
        scores[*it] = ScoreData(0, model);
        addChangeEvent(
                new AddScorePlayerNetworkEvent(model->getId(), players->getPlayer(*it)->getName(),
                        players->getPlayer(*it)->getColor()));
    }
}

void ScoreModel::handleEvent(const Event& event)
{
    event.visitScoreModel(this);
}

void ScoreModel::fullRows(int playerId, int noOfRows)
{
    int points = pow(2, noOfRows - 1) * 100;
    updateScore(playerId, points);
}

void ScoreModel::newRow(int playerId)
{
    updateScore(playerId, -50);
}

void ScoreModel::pieceDown(int playerId)
{
    updateScore(playerId, 10);
}

void ScoreModel::declareWinner()
{
    int winnerScore = INT_MIN;
    int winnerPlayer = 0;
    for (ScoreMap::iterator it = scores.begin(); it != scores.end(); ++it)
    {
        if (it->second.first > winnerScore)
        {
            winnerScore = it->second.first;
            winnerPlayer = it->first;
        }
    }
    addChangeEvent(new GameOverNetworkEvent(players->getPlayer(winnerPlayer)->getName()));
}

void ScoreModel::updateScore(int playerId, int points)
{
    scores[playerId].first += points;
    addChangeEvent(new UpdateScoreNetworkEvent(scores[playerId].second->getId(), scores[playerId].first));
}
